﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Sinacor.Infra.Core.Licensing;
using System.IO;
using Sinacor.Infra.UI.Security.Licensing.Infra.Security.Licensing;
using Sinacor.Infra.UI.Security.Services;
using Sinacor.Infra.UI.Session;
using PSE.Framework.Common.Security.Services.Configuration;

namespace Sinacor.Infra.UI.Security.Licensing
{
    public class LicensingManager
    {
        private static LicensingManager _licensingManager = null;
        private static LicensingValidator _licensingValidator;
        private static SignedLicensing _signedLicensing;
        private static SessionManager _sessionManager;
        private static Session.Session _session;
        private static Mutex mtx = new Mutex();

        public LicensingManager()
        {
            try
            {
                //Recupera os dados da sessão corrente
                _sessionManager = SessionManager.GetInstance();
                _session = _sessionManager.GetCurrentSession();

                //Lê do serviço o conteúdo do arquivo de licensing
                byte[] licensingByteArray = GetLicesingFromServer();

                //Cria o objeto de Licensing Assinado
                _signedLicensing = new SignedLicensing();

                try
                {
                    //Lê o arquivo de licenciamento carregando os dados para o objeto.
                    _signedLicensing.LoadLicensingFromByteArray(licensingByteArray);

                    //Cria o objeto de validação a partir da licença assinada que foi criada
                    _licensingValidator = new LicensingValidator(_signedLicensing);
                }
                catch (LicensingCorruptedException lcex)
                {
                    //TODO: Colocar Log de U.I
                    throw new Exception("Corrupted Licensing Data.", lcex);
                }
                catch (LicensingExpiredException leex)
                {
                    //TODO: Colocar Log de U.I
                    throw new Exception("Expired Licensing.", leex);
                }
            }
            catch (Exception ex)
            {
                //TODO: Colocar Log de U.I
                throw new Exception("Loading Licensing Fail.", ex);
            }
        }

        public byte[] GetLicesingFromServer()
        {
            byte[] result;

            using (ServiceInstance<ILicensing> si = new ServiceInstance<ILicensing>())
            {
                ILicensing service = si.TryGetInstance(_session.GenerateSessionInformation(), CriptographyLevelType.Federated);

                result = service.GetLincensing().BinaryLicense;
            }

            return result;
        }

        public static LicensingManager GetInstance()
        {
            mtx.WaitOne();
            try
            {
                if (_licensingManager == null)
                    _licensingManager = new LicensingManager();
            }
            catch (Exception ex)
            {
                mtx.ReleaseMutex();
                throw ex;
            }

            mtx.ReleaseMutex();

            return _licensingManager;
        }

        public bool ValidateCompany(string companyName, string companyCGC, int companyId)
        {
            bool result = false;

            lock (_licensingValidator)
            {
                _session = _sessionManager.GetCurrentSession();

                result = _licensingValidator.Validate(new Core.Licensing.Company(companyName, companyCGC, companyId));
            }

            return result;
        }

        public bool ValidateModule(string moduleID, bool plus)
        {
            bool result = false;

            lock (_licensingValidator)
            {
                _session = _sessionManager.GetCurrentSession();

                Core.Licensing.Company company = new Core.Licensing.Company(_session.Company.Name, _session.Company.CGC, _session.Company.Id);

                result = _licensingValidator.Validate(company, new Module() { Monogram = moduleID, Plus = plus });
            }

            return result;
        }

        public bool ValidateKernelPlus()
        {
            bool result = false;

            lock (_licensingValidator)
            {
                _session = _sessionManager.GetCurrentSession();

                Core.Licensing.Company company = new Core.Licensing.Company(_session.Company.Name, _session.Company.CGC, _session.Company.Id);

                result = _licensingValidator.Validate(company, new Module("Kernel+", "KNL", true));
            }

            return result;
        }

        public bool ValidateLicenseTrial(out int days_remaining)
        {
            bool result = false;

            lock (_licensingValidator)
            {
                result = _licensingValidator.ValidateLicenseTrial(out days_remaining);
            }

            return result;
        }
    }
}
